﻿using System;
using System.Linq;
using System.Collections.Generic;
using Light.Framework.Model;
using Light.Framework.Castle;
using NHibernate.Criterion;
using Light.Framework.Contract;
using Castle.ActiveRecord;
using System.Security.Permissions;
using System.Text;
using System.Data;
using Light.Utility;
using System.Data.Common;

namespace Light.Framework.Component
{
    /// <summary>
    /// 组件基类（包含通用的CRUD方法）
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class BaseComponent<T> where T : class, IEntity, new()
    {

        private ModelOrder modelOrder = new ModelOrder();
        private List<string> orderFields = new List<string>();
        private Dictionary<string, string> searchFields = new Dictionary<string, string>();

        /// <summary>
        /// 查询字段属性
        /// </summary>
        public virtual Dictionary<string, string> SearchFields
        {
            get
            {
                if (searchFields.Count == 0)
                {
                    T obj = new T();
                    Dictionary<string, string> dic = obj.GetSearchFields();
                    if (dic != null && dic.Keys.Count > 0)
                    {
                        searchFields = dic;
                    }
                }
                return searchFields;
            }
        }

        /// <summary>
        /// 排序字段
        /// </summary>
        public virtual List<string> OrderFields
        {
            get
            {
                if (orderFields.Count == 0)
                {
                    T obj = new T();
                    Dictionary<string, string> dic = obj.GetOrderFields();
                    if (dic != null && dic.Keys.Count > 0)
                    {
                        searchFields = dic;
                    }
                }
                return orderFields;
            }
        }

        /// <summary>
        /// 排序对象
        /// </summary>
        public virtual ModelOrder ModelOrder
        {
            get { return modelOrder; }
            set { modelOrder = value; }
        }


        #region 基本的CRUD方法

        //[AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Create(T obj)
        {
            OperateResult result = new OperateResult();

            if (obj.TimeCreated == default(DateTime))
                obj.TimeCreated = DateTime.Now;
            if (obj.TimeUpdated == default(DateTime))
                obj.TimeUpdated = DateTime.Now;
            if (obj.Organization == null)
            {
                obj.Organization = ServerApplication.User.Organization;
            }

            result = ValidateData(obj);
            if (!result.IsSucced)
            {
                return result;
            }

            ICriterion criterion = this.GetNotDeletedCriterion();
            criterion = Expression.And(criterion, CreateCriterion(obj));

            int countExits = EntityMediator<T>.Count(criterion);
            if (countExits > 0)
            {
                result.IsSucced = false;
                result.Message = GetExistMessage(obj);
            }
            else
            {
                result = Excute(EntityMediator<T>.Create, obj, OperateType.Create);
            }

            return result;
        }


        [AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Delete(int id)
        {
            OperateResult result = new OperateResult() { IsSucced = false };
            T obj = Get(id);
            return Delete(obj);
        }

        public virtual OperateResult Delete(int[] ids)
        {
            OperateResult result = new OperateResult();

            if (ids == null && ids.Length == 0)
            {
                result.IsSucced = false;
                result.Message = "请选择要删除的记录";

                return result;
            }

            int countSucced = 0;
            int countFailed = 0;
            StringBuilder builder = new StringBuilder();

            foreach (var id in ids)
            {
                T obj = Get(id);
                result = Delete(obj);

                if (result.IsSucced)
                {
                    countSucced++;
                }
                else
                {
                    countFailed++;
                    builder.Append(result.Message + ";");
                }
            }

            if (countFailed == ids.Length)
            {
                result.IsSucced = false;
                result.Message = builder.ToString();
            }
            else
            {
                result.IsSucced = true;
                result.Message = "成功删除" + countSucced + "条记录";

                if (countFailed > 0)
                {
                    ServerApplication.Logger.LogError(result.Message);
                }
            }

            return result;
        }

        //[AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Update(T obj)
        {
            OperateResult result = new OperateResult();

            obj.TimeUpdated = DateTime.Now;
            if (obj.Organization == null)
            {
                obj.Organization = ServerApplication.User.Organization;
            }

            result = ValidateData(obj);
            if (!result.IsSucced)
            {
                return result;
            }

            ICriterion criterion = this.GetNotDeletedCriterion();
            criterion = Expression.And(criterion, Expression.And(CreateCriterion(obj), Expression.Not(Expression.Eq("ID", obj.ID))));

            int countExits = EntityMediator<T>.Count(criterion);
            if (countExits > 0)
            {
                result.IsSucced = false;
                result.Message = GetExistMessage(obj);
            }
            else
            {
                result = Excute(EntityMediator<T>.Update, obj, OperateType.Update);
            }
            return result;

        }

        //[AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Save(T obj)
        {
            if (obj.IsNew)
            {
                return Create(obj);
            }
            else
            {
                return Update(obj);
            }
        }

        /// <summary>
        /// 验证数据（是否符合业务逻辑）
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual OperateResult ValidateData(T obj)
        {
            return new OperateResult() { IsSucced = true };
        }


        [AccessSecurity(SecurityAction.Demand)]
        public virtual OperateResult Delete(T obj)
        {
            OperateResult result = new OperateResult() { IsSucced = false };
            if (obj == null)
                result.Message = "没有符合条件的记录！";
            else
            {
                obj.IsDeleted = true;
                obj.TimeUpdated = DateTime.Now;
                result = Excute(EntityMediator<T>.Delete, obj, OperateType.Delete);
            }
            return result;
        }

        public virtual OperateResult Delete(IList<T> models)
        {
            OperateResult result = new OperateResult();

            bool isSucceed = true;
            if (models == null || models.Count == 0)
            {
                isSucceed = false;
                result.Message = "要删除的记录不能为空！";
            }
            else
            {
                StringBuilder builder = new StringBuilder();

                foreach (var model in models)
                {
                    result = Delete(model);
                    if (result.IsSucced == false)
                    {
                        isSucceed = false;
                        builder.Append(result.Message);
                    }
                }
                result.Message = builder.ToString();
            }
            result.IsSucced = isSucceed;

            return result;
        }


        [AccessSecurity(SecurityAction.Demand)]
        public virtual T Get(int id)
        {
            T model = null;
            try
            {
                model = EntityMediator<T>.Find(id);
                ServerApplication.Evit(model);
            }
            catch (Exception ex)
            {
                ServerApplication.Logger.LogError("试图获取一个不存在实体，ID：" + id.ToString() + " " + ex.Message);
            }

            return model;
        }

        /// <summary>
        /// 获取默认项，
        /// 若T实现了IDefaultable接口，则取IsDefault=true的对象
        /// 若未实现，则返回 new T();
        /// </summary>
        /// <returns></returns>
        public virtual T Get()
        {
            T obj = new T();

            if (obj is IDefaultable)
            {

                ICriterion criterion1 = GetOrganCriertion();
                criterion1 = Expression.And(criterion1, GetNotDeletedCriterion());
                ICriterion criterion2 = Expression.And(criterion1, Expression.Eq("IsDefault", true));

                obj = EntityMediator<T>.FindFirst(criterion2);
                if (obj == null)
                    obj = EntityMediator<T>.FindFirst(criterion1);

                return obj;
            }

            return obj;
        }

        [AccessSecurity(SecurityAction.Demand)]
        protected virtual T Get(ICriterion criterion)
        {
            return Get(criterion, false);
        }

        /// <summary>
        /// 获取单个对象
        /// </summary>
        /// <param name="criterion"></param>
        /// <param name="includeDeleted">是否包含已删除数据</param>
        /// <returns></returns>
        [AccessSecurity(SecurityAction.Demand)]
        protected virtual T Get(ICriterion criterion, bool includeDeleted)
        {
            if (!includeDeleted)
                criterion = Expression.And(criterion, GetNotDeletedCriterion());
            if (ServerApplication.User != null && !ServerApplication.User.IsSuper)
                criterion = Expression.And(criterion, GetOrganCriertion());

            T obj = EntityMediator<T>.FindFirst(criterion);
            ServerApplication.Evit(obj);

            return obj;
        }

        /// <summary>
        /// 不区分组织机构
        /// </summary>
        /// <returns></returns>
        [AccessSecurity(SecurityAction.Demand)]
        public virtual IList<T> GetAll()
        {
            IList<T> models = GetAll(GetDetachedCriteria(null));
            ServerApplication.Evit(models);
            return models;

        }

        [AccessSecurity(SecurityAction.Demand)]
        public virtual IList<T> GetAll(SearchArgs args)
        {
            return GetAll(GetDetachedCriteria(args));
        }


        public T Get(SearchArgs args)
        {
            return Get(args, ModelOrder);
        }


        /// <summary>
        /// 根据条件返回一条记录
        /// </summary>
        /// <param name="args">查询参数</param>
        /// <param name="order">排序字段</param>
        /// <returns></returns>
        public virtual T Get(SearchArgs args, ModelOrder order)
        {
            return Get(args, order, true);
        }

        /// <summary>
        /// 根据条件返回一条记录
        /// </summary>
        /// <param name="args">查询参数</param>
        /// <param name="order">排序字段</param>
        /// <param name="addOrgFilter">是否包含网点过滤条件</param>
        /// <returns></returns>
        public virtual T Get(SearchArgs args, ModelOrder order, bool addOrgFilter)
        {
            DetachedCriteria dc = null;

            if (args != null)
                dc = args.ToDetachedCriteria<T>();

            if (dc == null)
                dc = DetachedCriteria.For<T>();

            dc.Add(GetNotDeletedCriterion());
            if (addOrgFilter)
                dc.Add(GetOrganCriertion());

            T obj = EntityMediator<T>.FindFirst(dc, order.Orders);

            ServerApplication.Evit(obj);

            return obj;

        }


        /// <summary>
        /// 根据属性值获取单个实体
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public virtual T Get(string propertyName, object value)
        {
            return Get(propertyName, value, false);
        }


        /// <summary>
        /// 根据属性值获取单个实体
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        /// <param name="includeDeleted">是否包含已删除记录</param>
        /// <returns></returns>
        public virtual T Get(string propertyName, object value, bool includeDeleted)
        {
            ICriterion criterion = Expression.Eq(propertyName, value);

            if (!includeDeleted)
                criterion = Expression.And(criterion, GetNotDeletedCriterion());
            if (ServerApplication.Organization != null
                && ServerApplication.User != null
                && !ServerApplication.User.IsSuper)
            {
                criterion = Expression.And(criterion, GetOrganCriertion());
            }
            T obj = EntityMediator<T>.FindFirst(criterion);
            ServerApplication.Evit(obj);

            return obj;
        }

        /// <summary>
        /// 搜索：支持关联查询
        /// </summary>
        /// <param name="args"></param>
        /// <param name="pageIndex"></param>
        /// <param name="pageSize"></param>
        /// <param name="totalResult"></param>
        /// <returns></returns>
        public virtual IList<T> Search(SearchArgs args, int pageIndex, int pageSize, out int totalResult)
        {

            DetachedCriteria criterion = GetDetachedCriteria(args);
            return Search(criterion, pageIndex, pageSize, out totalResult);
        }


        [AccessSecurity(SecurityAction.Demand)]
        public virtual IList<T> Search(SearchArgs searchArgs, PageArgs pageArgs)
        {

            int totalResult = pageArgs.TotalResults;

            //ICriterion criterion = GetCriterion(searchArgs);
            DetachedCriteria criterion = GetDetachedCriteria(searchArgs);

            IList<T> result = Search(criterion, pageArgs.PageIndex, pageArgs.PageSize, out totalResult);

            pageArgs.TotalResults = totalResult;

            return result;
        }

        [AccessSecurity(SecurityAction.Demand)]
        public virtual DataTable SearchTable(SearchArgs searchArgs, PageArgs pageArgs)
        {

            int totalResult = pageArgs.TotalResults;

            //ICriterion criterion = GetCriterion(searchArgs);
            DetachedCriteria criterion = GetDetachedCriteria(searchArgs);

            IList<T> result = Search(criterion, pageArgs.PageIndex, pageArgs.PageSize, out totalResult);

            pageArgs.TotalResults = totalResult;

            if (result != null)
                return ImportHelper.ToDisplayTable<T>(result.ToArray());
            else
                return null;
        }

        /// <summary>
        /// 获取记录条数
        /// </summary>
        /// <returns></returns>
        public virtual int Count()
        {
            return Count(GetNotDeletedCriterion());
        }

        /// <summary>
        /// 获取记录条数
        /// </summary>
        /// <param name="searchArgs"></param>
        /// <returns></returns>
        public virtual int Count(SearchArgs searchArgs)
        {
            DetachedCriteria criterion = GetDetachedCriteria(searchArgs);
            return Count(criterion);
        }

        protected virtual IList<T> Search(ICriterion criterion, int pageIndex, int pageSize, out int totalResult)
        {
            using (TransactionScope ts = new TransactionScope(TransactionMode.New, OnDispose.Rollback))
            {
                try
                {
                    IList<T> models = null;

                    int totalPages = 0;

                    if (criterion != null)
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders, criterion);
                    }
                    else
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders);
                    }

                    ts.VoteCommit();
                    return models;
                }

                catch (Exception ex)
                {
                    ts.VoteRollBack();
                    ServerApplication.Logger.LogError(ex.Message);
                    throw ex;

                }
            }

        }

        protected virtual IList<T> Search(DetachedCriteria criterion, int pageIndex, int pageSize, out int totalResult)
        {
            using (TransactionScope ts = new TransactionScope(TransactionMode.New, OnDispose.Commit))
            {
                try
                {
                    IList<T> models = null;

                    int totalPages = 0;

                    if (criterion != null)
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders, criterion);
                    }
                    else
                    {
                        models = EntityMediator<T>.SlicedFindAll(ref pageIndex, out totalPages, out totalResult, pageSize, ModelOrder.Orders);
                    }

                    ts.VoteCommit();
                    return models;
                }

                catch (Exception ex)
                {
                    ts.VoteRollBack();
                    ServerApplication.Logger.LogError(ex.Message);
                    throw ex;

                }
            }

        }


        /// <summary>
        /// 查询条件（附加组织机构过滤条件）
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        protected virtual ICriterion GetCriterion(SearchArgs args)
        {
            ICriterion criterion = null;

            if (args != null)
                criterion = args.ToCriterion<T>();
            if (criterion == null)
                criterion = Expression.Sql("1=1");

            //非超级管理员仅能查看本网点下的信息
            if (ServerApplication.Organization != null
                && ServerApplication.User != null
                && ServerApplication.User.IsSuper == false)
            {

                IOrganizationComponent comp = ServerApplication.ComponentFactory.Create<IOrganizationComponent>();
                IList<Organization> list = comp.GetSubOrganization(ServerApplication.Organization, true);

                if (list.Count == 1)
                    criterion = Expression.And(criterion, Expression.Eq("Organization", list[0]));
                else
                    criterion = Expression.And(criterion, Expression.In("Organization", list.ToArray()));
            }
            else if (ServerApplication.User == null)
            {
                string msg = string.Format("User == null 设备：{0}  IP：{1} UA：{2} URL：{3}",
                    WebHelper.GetDevice(),
                    WebHelper.CurContext.Request.UserHostAddress,
                    WebHelper.CurContext.Request.UserAgent,
                    WebHelper.CurContext.Request.Url.ToString());
                ServerApplication.Logger.LogError(msg);
            }
            //else if (ServerApplication.User.IsSuper && ServerApplication.Organization == null)
            //{
            //    string msg = string.Format("IsSuper && Organization == null 设备：{0}  IP：{1} UA：{2} URL：{3}",
            //        WebHelper.GetDevice(),
            //        WebHelper.CurContext.Request.UserHostAddress,
            //        WebHelper.CurContext.Request.UserAgent,
            //        WebHelper.CurContext.Request.Url.ToString());
            //    ServerApplication.Logger.LogError(msg);
            //}

            if (ServerApplication.User == null || !ServerApplication.User.IsSuper)
            {
                criterion = Expression.And(criterion, GetNotDeletedCriterion());
            }

            return criterion;
        }

        /// <summary>
        /// 查询条件（附加组织机构过滤条件）
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        protected virtual DetachedCriteria GetDetachedCriteria(SearchArgs args)
        {
            DetachedCriteria dc = null;

            if (args != null)
                dc = args.ToDetachedCriteria<T>();
            if (dc == null)
            {
                dc = DetachedCriteria.For<T>();
                dc = dc.Add(Expression.Sql("1=1"));
            }

            //非超级管理员仅能查看本网点下的信息
            if (ServerApplication.Organization != null
                && ServerApplication.User != null
                && ServerApplication.User.IsSuper == false)
            {

                IOrganizationComponent comp = ServerApplication.ComponentFactory.Create<IOrganizationComponent>();
                IList<Organization> list = comp.GetSubOrganization(ServerApplication.Organization, true);
                ICriterion criterion = null;

                if (list.Count == 1)
                    criterion = Expression.Eq("Organization", list[0]);
                else
                    criterion = Expression.In("Organization", list.ToArray());
                dc.Add(criterion);
            }
            else if (ServerApplication.User == null)
            {
                string msg = string.Format("User == null 设备：{0}  IP：{1} UA：{2} URL：{3}",
                    WebHelper.GetDevice(),
                    WebHelper.CurContext.Request.UserHostAddress,
                    WebHelper.CurContext.Request.UserAgent,
                    WebHelper.CurContext.Request.Url.ToString());
                ServerApplication.Logger.LogError(msg);
            }
            //else if (ServerApplication.User.IsSuper && ServerApplication.Organization == null)
            //{
            //    string msg = string.Format("IsSuper && Organization == null 设备：{0}  IP：{1} UA：{2} URL：{3}",
            //        WebHelper.GetDevice(),
            //        WebHelper.CurContext.Request.UserHostAddress,
            //        WebHelper.CurContext.Request.UserAgent,
            //        WebHelper.CurContext.Request.Url.ToString());
            //    ServerApplication.Logger.LogError(msg);
            //}


            if (ServerApplication.User == null || !ServerApplication.User.IsSuper)
            {
                dc.Add(GetNotDeletedCriterion());
            }
            return dc;

        }

        /// <summary>
        /// 获取组织机构，及其子机构
        /// </summary>
        /// <returns></returns>
        public virtual ICriterion GetOrganization()
        {
            //非超级管理员仅能查看本网点下的信息
            if (ServerApplication.Organization != null)
            {
                IOrganizationComponent comp = ServerApplication.ComponentFactory.Create<IOrganizationComponent>();
                IList<Organization> list = comp.GetSubOrganization(ServerApplication.Organization, true);
                ICriterion criterion = null;

                if (list.Count == 1)
                    criterion = Expression.Eq("Organization", list[0]);
                else
                    criterion = Expression.In("Organization", list.ToArray());

                return criterion;
            }
            return null;
        }

        /// <summary>
        /// 执行增，删，改操作
        /// </summary>
        /// <param name="method">方法名</param>
        /// <param name="obj">操作对象</param>
        /// <param name="type">操作类型</param>
        /// <returns></returns>
        protected OperateResult Excute(Action<T> method, T obj, OperateType type)
        {
            if (type == OperateType.Create || type == OperateType.Update)
            {
                BeforeSave(obj);
            }

            OperateResult result = new OperateResult();
            try
            {
                if (obj.IsValidated == false)
                {
                    result.IsSucced = false;
                    result.Message = obj.GetErrorMessage();

                    return result;
                }
                switch (type)
                {
                    case OperateType.Create: result.Message = "添加失败！"; break;
                    case OperateType.Update: result.Message = "更新失败！"; break;
                    case OperateType.Delete: result.Message = "删除失败！"; break;
                    default: break;
                }

                using (TransactionScope ts = new TransactionScope(TransactionMode.Inherits)) //新版需要
                {
                    try
                    {
                        method(obj);
                        ts.VoteCommit();
                    }
                    catch (Exception ex)
                    {
                        ts.VoteRollBack();
                        throw ex;
                    }
                }
                result.IsSucced = true;
                string optStr = string.Empty;

                switch (type)
                {
                    case OperateType.Create: result.Message = "添加成功！"; break;
                    case OperateType.Update: result.Message = "更新成功！"; break;
                    case OperateType.Delete: result.Message = "删除成功！"; break;
                    default: break;
                }

                bool traceable = ReflectionHelper.HasAttribute<TraceableAttribute>(typeof(T));
                if (traceable)
                {
                    string name = ReflectionHelper.GetAttributeValue<TraceableAttribute>(typeof(T), "Name");
                    if (String.IsNullOrEmpty(name))
                    {
                        name = ReflectionHelper.GetDisplayName(typeof(T));
                    }
                    string message = string.Format("{0}【{1}】{2} 操作人：{3}", name, obj.ToString(), result.Message, ServerApplication.User != null ? ServerApplication.User.Name : "系统");
                    ServerApplication.Logger.LogOperation(message);
                }
            }
            catch (Exception ex)
            {

                result.IsSucced = false;

                if (ex.InnerException != null && ex.InnerException.InnerException != null)
                {
                    result.Message = ex.InnerException.InnerException.Message;
                    if (result.Message.ToUpper().Contains("FOREIGN KEY"))
                    {
                        //result.Message = " 数据正在使用中，" + result.Message;
                        result.Message = " 数据正在使用中,请先删除其他相关信息！";
                    }
                }
                else if (ex.InnerException != null)
                {
                    result.Message += " 错误详细：" + ex.InnerException.Message;
                }
                else
                {
                    result.Message += " 错误详细：" + ex.Message;
                }

                ServerApplication.Logger.LogError(result.Message);
            }
            if (result.IsSucced && (type == OperateType.Create || type == OperateType.Update))
            {
                AfterSaved(obj);
            }

            return result;
        }

        /// <summary>
        /// 将批量调用method方法返回的结果，汇总到一个返回值中
        /// 有一个成功，则成功；
        /// </summary>
        /// <param name="method">带一个类型为 T 的参数，且 返回值为OperateResult 的方法</param>
        /// <param name="models"></param>
        /// <returns></returns>
        protected OperateResult Excute(OperateDelegate<T> method, params T[] objs)
        {
            OperateResult result = new OperateResult();

            int countSucced = 0;
            StringBuilder builderError = new StringBuilder();

            foreach (var model in objs)
            {
                result = method(model);
                if (result.IsSucced)
                {
                    countSucced++;
                }
                else
                {
                    builderError.Append(result.Message + ";");
                }
            }
            if (countSucced > 0)
            {
                result.IsSucced = true;
                result.Message = "操作成功";
            }
            else
            {
                result.IsSucced = false;
                result.Message = builderError.ToString();
            }

            return result;
        }


        [AccessSecurity(SecurityAction.Demand)]
        protected virtual IList<T> GetAll(ICriterion criterion)
        {
            DetachedCriteria criteria = DetachedCriteria.For<DetachedCriteria>();
            if (criterion != null)
            {
                criteria.Add(criterion);
            }

            IList<T> models = EntityMediator<T>.FindAll(ModelOrder.Orders, criterion);

            ServerApplication.Evit<T>(models);

            return models;
        }
        [AccessSecurity(SecurityAction.Demand)]
        protected virtual IList<T> GetAll(DetachedCriteria criterion)
        {
            IList<T> models = null;
            if (criterion == null)
            {
                models = EntityMediator<T>.FindAll();
            }
            else
            {
                models = EntityMediator<T>.FindAll(ModelOrder.Orders, criterion);
            }

            ServerApplication.Evit<T>(models);

            return models;
        }

        /// <summary>
        /// 获取记录条数，含已删数据
        /// </summary>
        /// <param name="criterion"></param>
        /// <returns></returns>
        protected virtual int Count(ICriterion criterion)
        {
            int count = 0;
            if (criterion == null)
            {
                count = EntityMediator<T>.Count();
            }
            else
            {
                count = EntityMediator<T>.Count(criterion);
            }
            return count;
        }

        /// <summary>
        /// 获取记录条数，含已删数据
        /// </summary>
        /// <param name="dc"></param>
        /// <returns></returns>
        protected virtual int Count(DetachedCriteria dc)
        {
            int count = 0;
            if (dc == null)
            {
                count = EntityMediator<T>.Count();
            }
            else
            {
                count = EntityMediator<T>.Count(dc);
            }
            return count;
        }

        /// <summary>
        /// 保存（新增、修改）前执行
        /// </summary>
        /// <param name="obj"></param>
        protected virtual void BeforeSave(T obj) { }

        /// <summary>
        /// 保存（新增、修改）成功后执行
        /// </summary>
        /// <param name="obj"></param>
        protected virtual void AfterSaved(T obj) { }

        /// <summary>
        /// 数据库中是否存在
        /// </summary>
        /// <param name="criterion"></param>
        /// <returns></returns>
        protected virtual bool Exists(ICriterion criterion)
        {
            return Count(criterion) > 0;
        }

        /// <summary>
        /// 数据库中是否存在
        /// </summary>
        /// <param name="dc"></param>
        /// <returns></returns>
        protected virtual bool Exists(DetachedCriteria dc)
        {
            return Count(dc) > 0;
        }

        /// <summary>
        /// 当前网点下是否存在（未删除的记录）
        /// </summary>
        /// <param name="args"></param>
        /// <returns></returns>
        public virtual bool Exists(SearchArgs args)
        {
            return Count(args) > 0;
        }

        #endregion


        #region 批量导入

        /// <summary>
        /// 批量导入时分批次保存每批次的数量
        /// </summary>
        protected int SizePerBatch = 50;

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="models"></param>
        /// <returns></returns>
        public virtual OperateResult Import(List<T> models)
        {
            OperateResult result = Validate(models.ToArray());

            if (result.IsSucced)
            {
                #region 导入至DB

                int cntSucced = 0;
                int cntFailed = 0;

                int pageIndex = 1;

                StringBuilder builder = new StringBuilder();
                using (TransactionScope ts = new TransactionScope())
                {
                    try
                    {


                        List<T> tmpModels = GetByPage(models, pageIndex, SizePerBatch);
                        while (tmpModels != null && tmpModels.Count > 0)
                        {

                            //1.创建一个大的查询条件
                            ICriterion groupCriterion = null;
                            foreach (var model in tmpModels)
                            {
                                if (groupCriterion == null)
                                    groupCriterion = CreateCriterion(model);
                                else
                                    groupCriterion = Expression.Or(groupCriterion, CreateCriterion(model));
                            }

                            //2.分组从数据库取出符合条件的记录
                            IList<T> groupDbModels = EntityMediator<T>.FindAll(groupCriterion);

                            //3.逐个新增或更新
                            foreach (T model in tmpModels)
                            {
                                T dbModel = groupDbModels.FirstOrDefault(CreateFunc(model));
                                if (dbModel != null)
                                {
                                    cntFailed++;
                                    builder.Append(GetExistMessage(model));
                                }
                                else
                                {
                                    result = Save(model);
                                    if (result.IsSucced)
                                    {
                                        cntSucced++;
                                    }
                                    else
                                    {
                                        cntFailed++;
                                        builder.Append(result.Message);
                                    }
                                }
                            }

                            pageIndex++;
                            tmpModels = GetByPage(models, pageIndex, SizePerBatch);
                        }
                        if (cntSucced == 0 && cntFailed > 0)
                        {
                            result.IsSucced = false;
                            result.Message = builder.ToString();
                        }
                        else
                        {
                            result.IsSucced = true;
                            result.Message = builder.ToString() + "成功保存" + cntSucced + "条记录！";
                        }

                        ts.VoteCommit();
                    }
                    catch (Exception ex)
                    {
                        result.IsSucced = false;
                        result.Message = ex.Message;
                        ts.VoteRollBack();
                    }
                }
                #endregion
            }
            return result;
        }

        /// <summary>
        /// 导入
        /// </summary>
        /// <param name="ds"></param>
        /// <returns></returns>
        public virtual OperateResult Import(DataSet ds)
        {
            OperateResult result = new OperateResult();
            if (ds == null || ds.Tables.Count == 0)
            {
                result.IsSucced = false;
                result.Message = "导入的数据为空！";
            }
            else
            {
                List<T> models = new List<T>();
                foreach (DataTable dt in ds.Tables)
                {
                    models.AddRange(ImportHelper.ConvertTo<T>(dt, GetImportMapping()));
                }

                if (models != null && models.Count > 0)
                {
                    result = Import(models);
                }
                else
                {
                    result.IsSucced = false;
                    result.Message = "导入的数据为空！";
                }
            }
            return result;
        }

        /// <summary>
        /// 获取自定义 收费项名称
        /// </summary>
        /// <returns></returns>
        public virtual Dictionary<string, string> GetCustomNames()
        {
            return null;
        }

        /// <summary>
        /// 导入时，获取需要重命名的列字典《默认列名，实际列名》
        /// </summary>
        /// <returns></returns>
        protected virtual Dictionary<string, string> GetImportMapping()
        {

            Dictionary<string, string> customNames = GetCustomNames();

            if (customNames != null && customNames.Count > 0)
            {

                Dictionary<string, string> dicMapping = new Dictionary<string, string>();

                Dictionary<string, string> importFields = ReflectionHelper.GetImportFields<T>(false);

                foreach (var pName in customNames.Keys)
                {
                    if (importFields.Keys.Contains(pName))
                    {
                        string oldColumnName = importFields[pName];
                        string newColumnName = customNames[pName];

                        if (dicMapping.Keys.Contains(oldColumnName))
                            dicMapping[oldColumnName] = newColumnName;
                        else
                            dicMapping.Add(oldColumnName, newColumnName);

                    }
                }

                return dicMapping;
            }
            return customNames;
        }


        /// <summary>
        /// 批量新增时需要判断的ICriterion条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual ICriterion CreateCriterion(T model)
        {
            return Expression.Sql("1<>1");
        }

        /// <summary>
        /// 批量新增时需要判断的Func条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual Func<T, bool> CreateFunc(T model)
        {
            return m => m.ID == model.ID;
        }

        /// <summary>
        /// 批量更新时需要判断的ICriterion条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual ICriterion UpdateCriterion(T model)
        {
            return Expression.Eq("ID", model.ID);
        }

        /// <summary>
        /// 批量更新时需要判断的Func条件
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual Func<T, bool> UpdateFunc(T model)
        {
            return m => m.ID == model.ID;
        }

        /// <summary>
        /// 获取信息已存在时的提示信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        protected virtual string GetExistMessage(T model)
        {
            return model.ToString() + " 信息已存在";
        }

        #endregion

        #region   查询表或视图

        public DataTable GetAll(string tableOrViewName, SearchArgs searchArgs, ResultOrder resultOrder)
        {
            return DataTableMediator.GetAll(tableOrViewName, searchArgs, resultOrder);
        }

        public DataTable Search(string tableOrViewName, SearchArgs searchArgs, PageArgs pageArgs, ResultOrder resultOrder)
        {
            return DataTableMediator.Search(tableOrViewName, searchArgs, pageArgs, resultOrder);
        }

        public decimal Sum(string tableOrViewName, string columnName, SearchArgs searchArgs)
        {
            return DataTableMediator.Sum(tableOrViewName, columnName, searchArgs);
        }

        #endregion

        /// <summary>
        /// 从集合中分页获取数据
        /// </summary>
        /// <param name="models">数据集合</param>
        /// <param name="pageIndex">目标页码</param>
        /// <param name="pageSize">每页数量</param>
        /// <returns>指定页的数据</returns>
        internal List<T> GetByPage(List<T> models, int pageIndex, int pageSize)
        {
            if (models == null)
            {
                return models;
            }

            List<T> temp = new List<T>();

            int startIndex = (pageIndex - 1) * pageSize;
            int endIndex = pageIndex * pageSize;

            for (int i = startIndex; i < endIndex && i < models.Count; i++)
            {
                temp.Add(models[i]);
            }

            return temp;
        }

        OperateResult Validate(params T[] models)
        {
            OperateResult result = new OperateResult();

            if (models == null || models.Length == 0)
            {
                result.IsSucced = false;
                result.Message = "导入的记录为空！";
            }
            else
            {
                StringBuilder errorBuilder = new StringBuilder();
                int length = models.Length;

                for (int i = 0; i < length; i++)
                {
                    T model = models[i];
                    if (!model.IsValidated)
                    {
                        errorBuilder.Append("第" + (i + 1).ToString() + "行记录：" + model.GetErrorMessage() + " ");
                    }
                }
                result.IsSucced = errorBuilder.Length == 0;
                result.Message = errorBuilder.ToString();
            }
            return result;
        }

        /// <summary>
        /// 从当前应用程序域中获取值
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        protected void SetValue(string name, object value)
        {
            System.Threading.Thread.GetDomain().SetData(name, value);
        }

        /// <summary>
        /// 在当前线程应用程序域中设置值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="name"></param>
        /// <returns></returns>
        protected T GetValue<T>(string name)
        {
            T value = default(T);

            object obj = System.Threading.Thread.GetDomain().GetData(name);
            if (obj != null)
                value = (T)obj;

            return value;
        }

        /// <summary>
        /// 获取未删除的数据
        /// </summary>
        /// <returns></returns>
        protected ICriterion GetNotDeletedCriterion()
        {
            return Expression.Eq("IsDeleted", false);
        }

        /// <summary>
        /// 获取当前网点过滤条件(含下级网点)
        /// </summary>
        /// <returns></returns>
        protected ICriterion GetOrgansCriertion()
        {
            ICriterion criterion = Expression.Sql("1=1");

            if (ServerApplication.Organization != null
                && ServerApplication.User != null
                && ServerApplication.User.IsSuper == false)
            {
                IOrganizationComponent comp = ServerApplication.ComponentFactory.Create<IOrganizationComponent>();
                IList<Organization> list = comp.GetSubOrganization(ServerApplication.Organization, true);


                if (list.Count == 1)
                    criterion = GetOrganCriertion(list[0]);
                else
                    criterion = Expression.In("Organization", list.ToArray());
            }
            return criterion;
        }

        /// <summary>
        /// 获取当前网点过滤条件(不含下级网点)
        /// </summary>
        /// <returns></returns>
        protected ICriterion GetOrganCriertion()
        {
            return GetOrganCriertion(ServerApplication.Organization);
        }

        /// <summary>
        /// 获取网点过滤条件
        /// </summary>
        /// <returns></returns>
        protected ICriterion GetOrganCriertion(Organization organization)
        {
            if (organization != null)
            {
                return Expression.Eq("Organization", organization);
            }
            else
            {
                return Expression.Sql("1=1");
            }
        }

        /// <summary>
        /// 设置默认值
        /// </summary>
        /// <typeparam name="TD"></typeparam>
        /// <param name="obj"></param>
        protected virtual void SetDefault<TD>(TD obj) where TD : Entity, IDefaultable, new()
        {
            if (obj.IsDefault)
            {
                ICriterion criterion = Expression.Eq("IsDefault", true);
                criterion = Expression.And(criterion, GetOrganCriertion(obj.Organization));
                if (!obj.IsNew)
                {
                    criterion = Expression.And(criterion, Expression.Not(Expression.Eq("ID", obj.ID)));
                }

                ICriterion criterionDefault = GetDefaultCriterion(obj);
                if (criterionDefault != null)
                {
                    criterion = Expression.And(criterion, criterionDefault);
                }

                IList<TD> models = EntityMediator<TD>.FindAll(criterion);
                foreach (var model in models)
                {
                    if (model.ID != obj.ID)
                    {
                        model.IsDefault = false;
                        EntityMediator<TD>.Update(model);
                    }
                }
            }
        }

        /// <summary>
        /// 获取设置默认项的条件
        /// </summary>
        /// <returns></returns>
        protected virtual ICriterion GetDefaultCriterion<TD>(TD obj) where TD : Entity, IDefaultable, new()
        {
            return null;
        }

    }
}
